home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 7 / BBS in a Box - Macintosh - Volume VII (BBS in a Box) (January 1993).iso / Files / Prog / T / TCL⁄C 1.1.2 Update.cpt / THINK C 5.0 Folder / THINK Class Library 1.1 / Dialog classes / CDLOGDialog.c next >
Text File  |  1991-09-30  |  22KB  |  748 lines

  1. /******************************************************************************
  2.  CDLOGDialog.c
  3.  
  4.         Subclass of CDialog that can be create from DLOG/DITL
  5.         resources. The standard dialog items are represented
  6.         by their closest TCL analogs.
  7.         
  8.     SUPERCLASS = CDialog
  9.     
  10.     Copyright © 1991 Symantec Corporation. All rights reserved.
  11.     
  12.  
  13.  ******************************************************************************/
  14.  
  15. #include "CDLOGDialog.h"
  16. #include "CButton.h"
  17. #include "CCheckBox.h"
  18. #include "CRadioControl.h"
  19. #include "CIntegerText.h"
  20. #include "CPicture.h"
  21. #include "CIconPane.h"
  22. #include "CPaneBorder.h"
  23. #include "CRadioGroupPane.h"
  24. #include "CBartender.h"
  25. #include "TBUtilities.h"
  26. #include "CPanorama.h"
  27. #include "CList.h"
  28. #include <Packages.h>
  29.  
  30. typedef struct tItemList
  31. {
  32.     short        maxIndex;
  33.     tDITLItem    items[];
  34.     
  35. } tItemList, *tItemListPtr, **tItemListHndl;
  36.  
  37. extern CBartender *gBartender;
  38.  
  39. static void CollectUntil( char delimiter, StringPtr text, short *index, 
  40.                 StringPtr returnStr);
  41.  
  42. /******************************************************************************
  43.  IDLOGDialog
  44.      
  45.      Initialize a dialog window from DLOG/DITL resources.
  46. ******************************************************************************/
  47.  
  48. void CDLOGDialog::IDLOGDialog( short DLOGid, CDesktop *anEnclosure,
  49.                 CDirector *aSupervisor)
  50. {
  51.     DialogTHndl    dlogTemplate = NULL;
  52.     Rect        boundsRect;
  53.     SignedByte    savedState;
  54.     Boolean        makeScrollable;
  55.     
  56.     staticTextFont = editTextFont = 0;    /* use the system font                */
  57.     staticTextSize = editTextSize = 0;    /* use TE's default size            */
  58.     defaultBorderPen = 1;                /* default to border of 1 pixel     */
  59.     
  60.     
  61.                     /* Get the DLOG resource template                        */
  62.         
  63.     dlogTemplate = (DialogTHndl) GetResource( 'DLOG', DLOGid);
  64.     FailNILRes( dlogTemplate);
  65.     
  66.                     /* Get window size from the template                    */
  67.     boundsRect = (**dlogTemplate).boundsRect;
  68.         
  69.     /* If the procID is documentProc or zoomDocProc then give the window    */
  70.     /* horizontal and vertical scroll bars and a size box.                    */
  71.  
  72.     procID = (**dlogTemplate).procID;
  73.     makeScrollable = (procID == documentProc) || (procID == zoomDocProc);
  74.     
  75.     CDialog::INewDialog( &boundsRect, kNotVisible, procID, 
  76.                 (**dlogTemplate).goAwayFlag, anEnclosure, aSupervisor);
  77.     MakePanorama( makeScrollable, makeScrollable, makeScrollable);                
  78.                 
  79.     savedState = HGetState( (Handle) dlogTemplate);
  80.     HLock( (Handle) dlogTemplate);    
  81.     
  82.                 /* Get the window title from the template                    */
  83.             
  84.     SetTitle( (**dlogTemplate).title);
  85.     HSetState( (Handle) dlogTemplate, savedState);
  86.     
  87.                 /* Get the DITL resource and create all the dialog items    */
  88.     AddDITLItems( (**dlogTemplate).itemsID, 0);
  89.     
  90. }    /* CDialog::IDLOGDialog */            
  91.  
  92. /******************************************************************************
  93.  AddDITLItems
  94.  
  95.      Parse the DITL resource, and create the appropriate TCL panes.
  96.      A separate method is called for each item type, so it is not usually
  97.      necessary to override this method.
  98.      
  99. ******************************************************************************/
  100.  
  101. void CDLOGDialog::AddDITLItems( short DITLid, long baseID)
  102. {
  103.     tItemListHndl    itemList = NULL;
  104.     SignedByte        savedState;
  105.     short            currIndex, maxIndex, dataSize;
  106.     Boolean            fDisabled;
  107.     register tDITLItem    *ditlItem;
  108.     short            itemWidth, itemHeight;
  109.     LongPt            itemTopLeft;
  110.     CView            *enclosure;
  111.     CPane            *newItem;
  112.     
  113.     TRY
  114.     {
  115.                 /* Get the DITL item list                            */
  116.         itemList = (tItemListHndl) GetResource( 'DITL', DITLid);
  117.         FailNILRes( itemList);
  118.         
  119.         savedState = HGetState( (Handle) itemList);
  120.         MoveHHi( (Handle) itemList);
  121.         HLock( (Handle) itemList);
  122.         
  123.         maxIndex = (**itemList).maxIndex; /* index of last item in list */
  124.         ditlItem = (**itemList).items;      /* point to the first DITL item */
  125.         
  126.                 /* iterate over all the items in the DITL resource        */
  127.                 /* and create the TCL panes on the fly                    */
  128.                 
  129.         for (currIndex = 0; currIndex <= maxIndex; currIndex++)
  130.         {
  131.                 /* Is this item disabled?                                */
  132.             fDisabled = ditlItem->itemType & itemDisable;
  133.             
  134.                 /* Get size of the item, and the pad it for word        */
  135.                 /* alignment if necessary                                */
  136.                 
  137.             dataSize = ditlItem->itemLength;
  138.             if (dataSize & 1) ++dataSize;
  139.             
  140.                 /* Find the "best fit" enclosure for the new item        */
  141.                         
  142.             enclosure = FindEnclosingView( &ditlItem->itemRect);
  143.             
  144.                 /* Get the dimensions for the new item                    */
  145.                 
  146.             itemWidth = ditlItem->itemRect.right - ditlItem->itemRect.left;
  147.             itemHeight = ditlItem->itemRect.bottom - ditlItem->itemRect.top;
  148.             
  149.                 /* If the enclosure for the new item is not the dialog     */
  150.                 /* itself, then we should transform the top left to the */
  151.                 /* enclosure's coordinates.    Note that the item rect in     */
  152.                 /* ditlItem is passed unmodified to    the item creation     */
  153.                 /* methods.                                                */
  154.             
  155.             ((CPane*) enclosure)->WindToFrame( topLeft( ditlItem->itemRect), 
  156.                                 &itemTopLeft);
  157.             
  158.                 /* Switch on the item type. We must strip off the         */
  159.                 /* enable bit to do so.                                    */
  160.                 
  161.             switch( ditlItem->itemType & 0x7F)
  162.             {
  163.                         /* User Items        */
  164.                 case userItem:
  165.                     newItem = AddDITLUserItem( itemWidth, itemHeight, itemTopLeft.h,
  166.                                 itemTopLeft.v, enclosure, ditlItem);
  167.                     break;
  168.                     
  169.                         /* Push Buttons        */
  170.                 case ctrlItem + btnCtrl:
  171.                     newItem = AddDITLPushBtn( itemWidth, itemHeight, itemTopLeft.h, 
  172.                                 itemTopLeft.v, enclosure, ditlItem);
  173.                     break;
  174.                     
  175.                         /* Check boxes        */
  176.                 case ctrlItem + chkCtrl:
  177.                     newItem = AddDITLCheckBox( itemWidth, itemHeight, itemTopLeft.h, 
  178.                                 itemTopLeft.v, enclosure, ditlItem);
  179.                     break;
  180.  
  181.                         /* Radio Buttons    */
  182.                 case ctrlItem + radCtrl:
  183.                     newItem = AddDITLRadioBtn( itemWidth, itemHeight, itemTopLeft.h,
  184.                                 itemTopLeft.v, enclosure, ditlItem,
  185.                                 currIndex + baseID + 1);
  186.                     break;
  187.  
  188.                         /* 'CNTL' Resource Controls */
  189.                 case ctrlItem + resCtrl:
  190.                     newItem = AddDITLResControl( itemWidth, itemHeight, itemTopLeft.h,
  191.                                 itemTopLeft.v, enclosure, ditlItem);
  192.                     break;
  193.                     
  194.                         /* Static text        */
  195.                 case statText:
  196.                     newItem = AddDITLStatText( itemWidth, itemHeight, itemTopLeft.h,
  197.                                 itemTopLeft.v, enclosure, ditlItem);
  198.                     break;
  199.                     
  200.                         /* Edit text        */
  201.                 case editText:
  202.                     newItem = AddDITLEditText( itemWidth, itemHeight, itemTopLeft.h,
  203.                                 itemTopLeft.v, enclosure, ditlItem);
  204.                     break;
  205.                     
  206.                         /* Icons            */
  207.                 case iconItem:
  208.                     newItem = AddDITLIcon( itemWidth, itemHeight, itemTopLeft.h,
  209.                                 itemTopLeft.v, enclosure, ditlItem);
  210.                     break;
  211.                     
  212.                         /* Pictures            */
  213.                 case picItem:
  214.                     newItem = AddDITLPicture( itemWidth, itemHeight, itemTopLeft.h,
  215.                                 itemTopLeft.v, enclosure, ditlItem);
  216.                     break;
  217.                     
  218.                 default:
  219.                     newItem = NULL;
  220.                     break;
  221.             }
  222.             
  223.             if (newItem)
  224.             {
  225.                 /* Set the view ID of the new dialog item to its index in the DITL + */
  226.                 /* the base ID supplied by the caller.                              */
  227.                 
  228.                 newItem->SetID( currIndex + baseID + 1);
  229.                 if (fDisabled)
  230.                     /* +++ disable item? */;
  231.                 else
  232.                 {
  233.                     newItem->SetWantsClicks( TRUE);
  234.                 }
  235.             }
  236.             
  237.                 /* bypass C pointer arithmetic to point to next item */
  238.             ditlItem = (tDITLItem*) (((long) ditlItem) + dataSize + sizeof( tDITLItem));
  239.  
  240.         }
  241.         HSetState( (Handle) itemList, savedState);
  242.     }
  243.     CATCH
  244.     {
  245.         if (itemList)
  246.         {
  247.             HSetState( (Handle) itemList, savedState);
  248.         }
  249.     }
  250.     ENDTRY;
  251.  
  252. }    /* CDLOGDialog::AddDITLItems */
  253.  
  254. /******************************************************************************
  255.  FindEnclosingView
  256.  
  257.      Find the view that completely encloses the given rectangle. DITLs have
  258.      no concept of nested items, but we can allow nested views to be specified
  259.      by checking whether the rectangle of an new item is completely
  260.      enclosed by the rectangle of any existing items.
  261.      The rectangle is taken to be in Window coordinates.
  262. ******************************************************************************/
  263.  
  264.     typedef struct tEnclViewInfo
  265.     {
  266.         Rect    boundsRect;
  267.         CView   *enclosingView;
  268.         
  269.     } tEnclViewInfo;
  270.  
  271.     static Boolean View_FindEnclosing( CObject *aView, long infoAddr)
  272.     {
  273.         CView *view = (CView*) aView;
  274.         CView *subview = NULL;
  275.         tEnclViewInfo *viewInfo = (tEnclViewInfo*) infoAddr;
  276.         
  277.         /* first check if the current view encloses the rect */
  278.         /* if it does, then check if any subview encloses it */
  279.         
  280.         if (view->Contains( topLeft( viewInfo->boundsRect)) &&
  281.             view->Contains( botRight( viewInfo->boundsRect)))
  282.         {
  283.             if (view->itsSubviews)
  284.             {
  285.                 subview = (CView*) view->itsSubviews->FirstSuccess1((TestFunc1) View_FindEnclosing,
  286.                             infoAddr);
  287.             }
  288.             
  289.             /* save the most specific view that encloses the rect,    */
  290.             /* either a subview of this view, or this view            */
  291.             
  292.             if (!viewInfo->enclosingView)    /* TCL 1.1.1 DLP 9/30/91 */
  293.                 viewInfo->enclosingView = subview? subview : view;
  294.             return TRUE;
  295.         }
  296.         else return FALSE;
  297.     }
  298.     
  299. CView *CDLOGDialog::FindEnclosingView( Rect *boundsRect)
  300. {
  301.     CView *foundView = NULL;
  302.     tEnclViewInfo  viewInfo;
  303.     
  304.     if (itsSubviews)
  305.     {
  306.         viewInfo.boundsRect = *boundsRect;
  307.         viewInfo.enclosingView = NULL;
  308.         foundView = (CView*) itsSubviews->FirstSuccess1( (TestFunc1) View_FindEnclosing,
  309.                         (long) &viewInfo);
  310.                         
  311.         /* If foundView is not nil, then some subview encloses    */
  312.         /* the rect. However, there may be a view nested within */
  313.         /* foundView that completely encloses the rect.         */
  314.         /* viewInfo.enclosingView returns the best view            */
  315.         
  316.         foundView = viewInfo.enclosingView;
  317.     }
  318.     
  319.     /* if no subview was found that completely encloses boundsRect */    
  320.     /* then the enclosure defaults to the dialog itself */
  321.             
  322.     return foundView? foundView : itsPanorama;
  323.  
  324. }    /* CDLOGDialog::FindEnclosingView */
  325.  
  326. /******************************************************************************
  327.  AddDITLPushBtn
  328.  
  329.      Add a button.
  330. ******************************************************************************/
  331.  
  332. CPane *CDLOGDialog::AddDITLPushBtn( short aWidth, short aHeight, short hEncl,
  333.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  334. {
  335.     CButton *btn;
  336.     Str255  titleStr;
  337.     long    cmd;
  338.     
  339.     /* make a copy of the button title */
  340.     
  341.     CopyPString( &ditlItem->itemLength, titleStr);
  342.     
  343.     /* ask the bartender to parse this string for us. */
  344.     gBartender->ParseItemString( titleStr, &cmd);
  345.     
  346.     btn = new( CButton);
  347.     btn->INewButton( aWidth, aHeight, hEncl, vEncl, titleStr, TRUE,
  348.             pushButProc, enclosure, this);
  349.     btn->SetClickCmd( cmd);
  350.             
  351.     return btn;
  352.  
  353. }    /* CDLOGDialog::AddDITLPushBtn */
  354.  
  355. /******************************************************************************
  356.  AddDITLRadioBtn
  357.  
  358.      Add a radio button.
  359. ******************************************************************************/
  360.  
  361. CPane *CDLOGDialog::AddDITLRadioBtn( short aWidth, short aHeight, short hEncl,
  362.                         short vEncl, CView *enclosure, tDITLItem *ditlItem,
  363.                         long anID)
  364. {
  365.     CRadioControl *radio = new( CRadioControl);
  366.     
  367.     ASSERT( member( enclosure, CRadioGroupPane));
  368.     
  369.     radio->INewRadioControl( aWidth, aHeight, hEncl, vEncl, &ditlItem->itemLength,
  370.                 TRUE, enclosure, enclosure);
  371.                 
  372.     return radio;
  373.  
  374. }    /* CDLOGDialog::AddDITLRadioBtn */
  375.  
  376. /******************************************************************************
  377.  AddDITLCheckBox
  378.  
  379.      Add a checkbox
  380. ******************************************************************************/
  381.  
  382. CPane *CDLOGDialog::AddDITLCheckBox( short aWidth, short aHeight, short hEncl,
  383.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  384. {
  385.     CCheckBox *check = new( CCheckBox);
  386.     
  387.     check->INewCheckBox( aWidth, aHeight, hEncl, vEncl, &ditlItem->itemLength, 
  388.                         TRUE, enclosure, this);
  389.                         
  390.     return check;
  391.  
  392. }    /* CDLOGDialog::AddDITLCheckBox */
  393.  
  394. /******************************************************************************
  395.  AddDITLResControl
  396.  
  397.      Resource controls are not supported by this class.
  398. ******************************************************************************/
  399.  
  400. CPane *CDLOGDialog::AddDITLResControl( short aWidth, short aHeight, short hEncl,
  401.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  402. {
  403.     return NULL;
  404.  
  405. }    /* CDLOGDialog::AddDITLResControl */
  406.  
  407. /******************************************************************************
  408.  AddDITLStatText
  409.  
  410.      Add a static text item. If the item text begins with the character '@',
  411.      it is considered an overloaded item and the rest of the text is passed
  412.      to the AddOverloadedItem method.
  413.      The text font and size are controlled by the staticTextFont and
  414.      staticTextSize instance variables.
  415. ******************************************************************************/
  416.  
  417. CPane *CDLOGDialog::AddDITLStatText( short aWidth, short aHeight, short hEncl,
  418.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  419. {
  420.     CEditText            *text;
  421.     unsigned char        length;
  422.     Str255                itemText;
  423.     
  424.     /* first check for overloading of static text items        */
  425.     /* overloading is signalled by a first character of '@' */
  426.     
  427.     if ( (* (char*) ditlItem->itemData) == '@')
  428.     {
  429.         length = Min( ditlItem->itemLength - 1, 255);
  430.         BlockMove( ((char*) ditlItem->itemData) + 1, &itemText[1], length);
  431.         itemText[0] = length;
  432.         
  433.         return AddOverloadedItem( itemText, aWidth, aHeight, hEncl, vEncl,
  434.                 enclosure, ditlItem);
  435.     }
  436.     else
  437.     {
  438.         text = new( CEditText);
  439.         text->IEditText( enclosure, this, aWidth, aHeight,
  440.                     hEncl, vEncl,
  441.                     sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
  442.         text->Specify( kNotEditable, kNotSelectable, kNotStylable);
  443.                     
  444.         text->SetFontNumber( staticTextFont);
  445.         if (staticTextSize > 0)
  446.             text->SetFontSize( staticTextSize);
  447.         
  448.         if (ditlItem->itemLength)
  449.             text->SetTextPtr( (Ptr) ditlItem->itemData, ditlItem->itemLength);
  450.                         
  451.         return text;
  452.     }
  453.  
  454. }    /* CDLOGDialog::AddDITLStatText */
  455.  
  456. /******************************************************************************
  457.  AddDITLEditText
  458.  
  459.      Add an edit text item.     The text font and size are controlled by the 
  460.      editTextFont and editTextSize instance variables.
  461.  
  462. *******************************************************************************/
  463.  
  464. CPane *CDLOGDialog::AddDITLEditText( short aWidth, short aHeight, short hEncl,
  465.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  466. {    
  467.     CDialogText *text;
  468.     
  469.     text = new( CDialogText);
  470.     text->IDialogText( enclosure, this, aWidth, aHeight,
  471.                 hEncl, vEncl,
  472.                 sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
  473.                 
  474.     text->SetFontNumber( editTextFont);
  475.     if (editTextSize > 0)
  476.         text->SetFontSize( editTextSize);
  477.     
  478.     if (ditlItem->itemLength)
  479.         text->SetTextPtr( (Ptr) ditlItem->itemData, ditlItem->itemLength);
  480.                     
  481.     return text;
  482.  
  483. }    /* CDLOGDialog::AddDITLEditText */
  484.  
  485. /******************************************************************************
  486.  AddDITLIcon
  487.  
  488.      Add an icon
  489. ******************************************************************************/
  490.  
  491. CPane *CDLOGDialog::AddDITLIcon( short aWidth, short aHeight, short hEncl,
  492.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  493. {
  494.     CIconPane *icon;
  495.     
  496.     icon = new( CIconPane);
  497.     icon->IIconPane( enclosure, this, hEncl, vEncl,
  498.                 sizFIXEDSTICKY, sizFIXEDSTICKY, ditlItem->itemData[0], 
  499.                 TRUE);
  500.         
  501.     return icon;
  502.  
  503. }    /* CDLOGDialog::AddDITLIcon */
  504.  
  505. /******************************************************************************
  506.  AddDITLPicture
  507.  
  508.      Add a picture
  509. ******************************************************************************/
  510.  
  511. CPane *CDLOGDialog::AddDITLPicture( short aWidth, short aHeight, short hEncl,
  512.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  513. {
  514.     CPicture *pict = new( CPicture);
  515.     
  516.     pict->IPicture( enclosure, this, aWidth, aHeight, 
  517.             hEncl, vEncl, sizFIXEDSTICKY, sizFIXEDSTICKY);
  518.     
  519.     pict->UsePICT( ditlItem->itemData[0]); /* pass resource ID of PICT */
  520.     
  521.     return pict;
  522.  
  523. }    /* CDLOGDialog::AddDITLPicture */
  524.  
  525. /******************************************************************************
  526.  AddDITLUserItem
  527.  
  528.      Add a user item. User items are converted to simple bordered panes
  529.      that use the defaultBorderPen thickness.
  530. ******************************************************************************/
  531.  
  532. CPane *CDLOGDialog::AddDITLUserItem( short aWidth, short aHeight, short hEncl,
  533.                         short vEncl, CView *enclosure, tDITLItem *ditlItem)
  534. {
  535.     CPane *pane = new( CPane);
  536.     CPaneBorder *border;
  537.     Rect    margin;
  538.     
  539.     pane->IPane( enclosure, this, aWidth, aHeight, hEncl, vEncl,
  540.                 sizFIXEDSTICKY, sizFIXEDSTICKY);
  541.  
  542.     border = new( CPaneBorder);
  543.     border->IPaneBorder( kBorderFrame);
  544.     border->SetPenSize( defaultBorderPen, defaultBorderPen);
  545.  
  546.     pane->SetBorder( border);
  547.     
  548.     return pane;
  549.  
  550. }    /* CDLOGDialog::AddDITLUserItem */
  551.  
  552.  
  553. /******************************************************************************
  554.  AddOverloadedItem
  555.  
  556.      View types that have no direct dialog mgr analog may be added
  557.      by overloading the static text item. The types support are:
  558.      
  559.      TYPE                        STATIC TEXT
  560.      ----                        -----------
  561.      
  562.      Any Pane resource            @$ClassName$ResType$ResID
  563.                                  e.g. @CPopupMenuPane$Popm$1000
  564.                                  would create a CPopupMenuPane from the template in 
  565.                                  the resource 'Popm' 1000. The size and location
  566.                                  of the pane are taken from the dialog item rect,
  567.                                  not from the resource.
  568.                                  
  569.      CRadioGroupPane                @RadioGroupPane
  570.      
  571.      
  572.      CIntegerText                @# must be first two characters
  573.                                  To supply min and max values enter
  574.                                  @#<min>#<max>,
  575.                                   
  576.                                  e.g. @#100#200 (see Demo.π.rsrc DITL 1026)
  577.                                  
  578.      CDialogText/ constraints    @!!        - creates required field, no max length
  579.                                  @!<num> - not required, max length is num
  580.                                            e.g. @!10 max length is 10
  581.                                  @!!<num> - required field with max length
  582.                                               e.g. @!!10
  583.                                               
  584.      Other overloaded types may be created by overriding this method.
  585.      
  586. ******************************************************************************/
  587.  
  588. CPane *CDLOGDialog::AddOverloadedItem( StringPtr itemText, short aWidth, short aHeight, 
  589.                     short hEncl, short vEncl,
  590.                     CView *enclosure, tDITLItem *ditlItem)
  591. {
  592.     Str255            numStr;
  593.     short            index;
  594.         
  595.     if (Length( itemText) == 0) return NULL;
  596.     
  597.     if (itemText[1] == '$')                // Create from resource
  598.     {
  599.         ResType     type;
  600.         long        resID;
  601.         Str255      className;
  602.         CPane        *newPane;
  603.         PaneTemp     savedTemplate, *theTemp;
  604.         Handle        templateRes;
  605.         SignedByte    savedState;
  606.         
  607.             // collect the class name, resource type and ID
  608.         index = 2;
  609.         CollectUntil( '$', itemText, &index, className);
  610.         if (Length( className) == 0) return;
  611.  
  612.         ++index;
  613.         CollectUntil( '$', itemText, &index, numStr);
  614.         if (Length( numStr) == 0) return;
  615.  
  616.         BlockMove( &numStr[1], &type, sizeof(ResType));
  617.         ++index;
  618.         CollectUntil( ' ', itemText, &index, numStr);
  619.         if (Length( numStr) == 0) return;
  620.  
  621.         StringToNum( numStr, &resID);
  622.         
  623.             // get the resource, save the location and size, then
  624.             // restore it after the pane is created.
  625.             
  626.         templateRes = GetResource( type, resID);
  627.         FailNILRes( templateRes);
  628.         savedState = HGetState( templateRes);
  629.         HNoPurge( templateRes);
  630.         
  631.         theTemp = *(PaneTemp**) templateRes;
  632.         savedTemplate = **(PaneTemp**)templateRes;
  633.         theTemp->width = aWidth;
  634.         theTemp->height = aHeight;
  635.         theTemp->hEncl = hEncl;
  636.         theTemp->vEncl = vEncl;
  637.  
  638.             // now make the pane
  639.         
  640.         newPane = new_by_name( PtoCstr(className));
  641.         if (!newPane) Failure( paramErr, excNewByNameFailed);
  642.         
  643.         ASSERT( member( newPane, CPane));
  644.         
  645.         newPane->IViewRes( type, resID, enclosure, this);
  646.     
  647.         HSetState( templateRes, savedState);
  648.         **(PaneTemp**) templateRes = savedTemplate; /* TCL 1.1.1 DLP 9/18/91 */
  649.         
  650.         return newPane;    
  651.     }
  652.     else if (itemText[1] == '#')        // Create a CIntegerText
  653.     {
  654.         long            min, max;
  655.         CIntegerText    *text  = new CIntegerText;
  656.         
  657.         text->IIntegerText( enclosure, this, aWidth, aHeight,
  658.                     hEncl, vEncl,
  659.                     sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
  660.                     
  661.         text->SetFontNumber( editTextFont);
  662.         if (editTextSize > 0)
  663.             text->SetFontSize( editTextSize);
  664.             
  665.         index = 2;
  666.         min = MINLONG;
  667.         max = MAXLONG;
  668.         
  669.         CollectUntil( '#', itemText, &index, numStr);
  670.         if (Length( numStr)) StringToNum( numStr, &min);
  671.         
  672.             // check if string not exhausted and have another '#'
  673.             
  674.         if ((index < Length(itemText)) && (itemText[index] == '#'))
  675.         {
  676.             index++;    // move past delimiter
  677.             CollectUntil( '#', itemText, &index, numStr);
  678.             if (Length( numStr)) StringToNum( numStr, &max);        
  679.         }
  680.         text->SpecifyRange( min, max);
  681.         
  682.         return text;
  683.         
  684.     }
  685.     else if (itemText[1] == '!')    // Create a CDialogText with constraints
  686.     {
  687.         Boolean        required = FALSE;
  688.         short        index = 2;
  689.         long        maxChars = MAXLONG;
  690.         
  691.         CDialogText *text = new CDialogText;
  692.  
  693.         text->IDialogText( enclosure, this, aWidth, aHeight,
  694.                     hEncl, vEncl,
  695.                     sizFIXEDSTICKY, sizFIXEDSTICKY, -1);
  696.                     
  697.         text->SetFontNumber( editTextFont);
  698.         if (editTextSize > 0)
  699.             text->SetFontSize( editTextSize);
  700.             
  701.         // if next char is another '!', make this a required field
  702.         if (itemText[2] == '!')
  703.         {
  704.             index++;
  705.             required = TRUE;
  706.         }
  707.         // next text, if any, is max number of chars, no
  708.         // trailing delimiter is required, just collect until end of string
  709.         CollectUntil( '!', itemText, &index, numStr);
  710.         if (Length( numStr)) StringToNum( numStr, &maxChars);
  711.         
  712.         text->SetConstraints( required, maxChars);
  713.         
  714.         return text;
  715.     }
  716.     else if (EqualString( itemText, "\pRadioGroupPane", FALSE, FALSE))
  717.     {
  718.         CPaneBorder    *border;
  719.         CRadioGroupPane *group = new CRadioGroupPane;
  720.         
  721.         group->IRadioGroupPane( enclosure, this, aWidth, aHeight,
  722.                         hEncl, vEncl, sizFIXEDSTICKY, sizFIXEDSTICKY);
  723.         border = new CPaneBorder;
  724.         border->IPaneBorder( kBorderFrame);
  725.         border->SetPenSize( defaultBorderPen, defaultBorderPen);
  726.         group->SetBorder( border);    
  727.         
  728.         return group;    
  729.     }
  730.     
  731.     return NULL;
  732.  
  733. }    /* CDLOGDialog::AddOverloadedItem */
  734.  
  735. static void CollectUntil( char delimiter, StringPtr text, short *index, 
  736.                 StringPtr returnStr)
  737. {
  738.     short i = *index, limit = Length( text);
  739.     
  740.     Length( returnStr) = 0;
  741.     while ((text[i] != delimiter) && (i <= limit))
  742.     {
  743.         returnStr[ ++returnStr[0]] = text[i++];
  744.     }
  745.     if ( i > limit) i = limit;
  746.     *index = i;
  747.  
  748. }